package com.mall.ware.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mall.common.constant.WareConstant;
import com.mall.common.page.PageData;
import com.mall.common.service.impl.CrudServiceImpl;
import com.mall.common.utils.ConvertUtils;
import com.mall.common.utils.ParamUtils;
import com.mall.ware.dao.PurchaseDao;
import com.mall.ware.dto.PurchaseDTO;
import com.mall.ware.entity.PurchaseDetailEntity;
import com.mall.ware.entity.PurchaseEntity;
import com.mall.ware.service.PurchaseDetailService;
import com.mall.ware.service.PurchaseService;
import com.mall.ware.service.WareSkuService;
import com.mall.ware.vo.MergeVo;
import com.mall.ware.vo.PurchaseFinishVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 采购信息
 *
 * @author xjc xjc@163.com
 * @since 1.0.0 2022-07-17
 */
@Service
public class PurchaseServiceImpl extends CrudServiceImpl<PurchaseDao, PurchaseEntity, PurchaseDTO> implements PurchaseService {

    @Resource
    private PurchaseDetailService purchaseDetailService;

    @Resource
    private WareSkuService wareSkuService;
    @Override
    public QueryWrapper<PurchaseEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("id");

        QueryWrapper<PurchaseEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);

        return wrapper;
    }


    @Override
    public PageData<PurchaseDTO> queryPageByCondition(Map<String, Object> params) {
        String key = ParamUtils.strParseString(params.get("key"));
        String status = ParamUtils.strParseString(params.get("status"));
        QueryWrapper<PurchaseEntity> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(key))
            wrapper.and(q -> q.eq("id", key).or().eq("assignee_name", key).or().eq("assignee_id", key));
        wrapper.eq(StringUtils.isNotBlank(status), "status", status);
        IPage<PurchaseEntity> selectPage = baseDao.selectPage(getPage(params, null, false), wrapper);
        return new PageData<>(ConvertUtils.sourceToTarget(selectPage.getRecords(), PurchaseDTO.class), selectPage.getTotal());
    }

    @Override
    public PageData<PurchaseDTO> queryNuReceiveByCondition(Map<String, Object> params) {
        QueryWrapper<PurchaseEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 0).or().eq("status", 1);
        IPage<PurchaseEntity> selectPage = baseDao.selectPage(getPage(params, null, false), wrapper);
        return new PageData<>(ConvertUtils.sourceToTarget(selectPage.getRecords(), PurchaseDTO.class), selectPage.getTotal());
    }

    @Transactional
    @Override
    public void mergePurchase(MergeVo mergeVo) {
        Long purchaseId = mergeVo.getPurchaseId();
        if (purchaseId == null || purchaseId == 0) {
            PurchaseEntity purchaseEntity = new PurchaseEntity();
            purchaseEntity.setStatus(WareConstant.PurchaseStatus.CREATE.getCode());
            purchaseEntity.setCreateTime(DateTime.now());
            purchaseEntity.setUpdateTime(DateTime.now());
            baseDao.insert(purchaseEntity);
            purchaseId = purchaseEntity.getId();
        }
        Long finalPurchaseId = purchaseId;
        List<PurchaseDetailEntity> collect = mergeVo.getItems()
                .stream()
                .filter(id -> {
                    PurchaseDetailEntity purchaseDetailEntity = purchaseDetailService.selectById(id);
                    return (purchaseDetailEntity != null &&
                            (purchaseDetailEntity.getStatus() == WareConstant.PurchaseDetailsStatus.CREATE.getCode()
                                    || purchaseDetailEntity.getStatus() == WareConstant.PurchaseDetailsStatus.ASSIGNED.getCode()));
                })
                .map(item -> {
                    PurchaseDetailEntity purchaseDetail = new PurchaseDetailEntity();
                    purchaseDetail.setPurchaseId(finalPurchaseId);
                    purchaseDetail.setId(item);
                    purchaseDetail.setStatus(WareConstant.PurchaseDetailsStatus.ASSIGNED.getCode());
                    return purchaseDetail;
                }).collect(Collectors.toList());
        purchaseDetailService.updateBatchById(collect);
        PurchaseEntity purchase = new PurchaseEntity();
        purchase.setId(purchaseId);
        purchase.setUpdateTime(DateTime.now());
        baseDao.updateById(purchase);
    }

    @Override
    public void updatePurchase(PurchaseDTO dto) {
        PurchaseEntity purchase = new PurchaseEntity();
        BeanUtil.copyProperties(dto, purchase);
        purchase.setUpdateTime(DateTime.now());
        baseDao.updateById(purchase);
    }

    @Transactional
    @Override
    public void receivePurchase(Long[] ids) {
        // 采购单状态
        List<PurchaseEntity> purchaseEntities = Arrays.stream(ids)
                .map(id -> baseDao.selectById(id))
                .filter(item -> item.getStatus() == WareConstant.PurchaseStatus.CREATE.getCode() || item.getStatus() == WareConstant.PurchaseDetailsStatus.ASSIGNED.getCode())
                .peek(item -> {
                    item.setStatus(WareConstant.PurchaseStatus.RECEIVE.getCode());
                    item.setUpdateTime(DateTime.now());
                })
                .collect(Collectors.toList());
        updateBatchById(purchaseEntities);
        // 采购项状态
        purchaseEntities.forEach((item) -> {
            List<PurchaseDetailEntity> detailEntities = purchaseDetailService.listByPurchaseId(item.getId());
            List<PurchaseDetailEntity> updateEntities = detailEntities.stream().map(detail -> {
                PurchaseDetailEntity detailDTO = new PurchaseDetailEntity();
                detailDTO.setId(detail.getId());
                detailDTO.setStatus(WareConstant.PurchaseDetailsStatus.BUYING.getCode());
                return detailDTO;
            }).collect(Collectors.toList());
            purchaseDetailService.updateBatchById(updateEntities);
        });
    }

    @Transactional
    @Override
    public void donePurchase(PurchaseFinishVo purchaseFinishVo) {
        Long id = purchaseFinishVo.getId();
        AtomicBoolean flag = new AtomicBoolean(true);
        List<PurchaseDetailEntity> updateData = new ArrayList<>();
        purchaseFinishVo.getItems().forEach(item->{
            PurchaseDetailEntity purchaseDetail = new PurchaseDetailEntity();
            if (item.getStatus()==WareConstant.PurchaseDetailsStatus.ERROR.getCode()){
                flag.set(false);
                purchaseDetail.setStatus(WareConstant.PurchaseDetailsStatus.ERROR.getCode());
            }else {
                purchaseDetail.setStatus(WareConstant.PurchaseDetailsStatus.FINISH.getCode());
                // 入库
                PurchaseDetailEntity purchaseDetail1 = purchaseDetailService.selectById(item.getPurchaseDetailId());
                wareSkuService.addStock(purchaseDetail1.getSkuId(),purchaseDetail1.getWareId(),purchaseDetail1.getSkuNum());
            }
            purchaseDetail.setId(item.getPurchaseDetailId());
            updateData.add(purchaseDetail);
        });
        purchaseDetailService.updateBatchById(updateData);
        PurchaseEntity purchase = new PurchaseEntity();
        purchase.setId(id);
        purchase.setUpdateTime(DateTime.now());
        purchase.setStatus(flag.get() ? WareConstant.PurchaseStatus.FINISH.getCode():WareConstant.PurchaseStatus.ERROR.getCode());
        baseDao.updateById(purchase);

    }
}